import { useGLTF } from "@react-three/drei";
import { useThree } from "@react-three/fiber";
import { useEffect, useState, useRef } from "react";
// 引入gltf模型加载库GLTFLoader.js
import { GLTFLoader, GLTF } from "three/addons/loaders/GLTFLoader.js";
// 引入draco压缩库
import { DRACOLoader } from "three/examples/jsm/Addons.js";
import * as THREE from "three";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { AnimateModel } from "./AnimateModel";
import gsap from "gsap";

interface props {
  /**
   * 环境贴图
   */
  evMap?: THREE.DataTexture;
  gui: GUI;
}
export function Model({ evMap, gui }: props) {
  const planeGeometry = useRef<THREE.PlaneGeometry | null>(null);
  const planeMesh = useRef<THREE.Mesh | null>(null);

  const [GLTF, setGLTF] = useState<GLTF>();
  const { scene } = useThree();

  const changePlaneGeometry = () => {
    if (planeGeometry.current) {
      planeGeometry.current.rotateX(Math.PI / 2);
    }
  };
  // 加载模型

  const addModel = () => {
    const glbLoader = new GLTFLoader();
    glbLoader.load("/glb/ferrari.glb", (gltf) => {
      /**
       * 模型加载后旋转90度
       */
      setGLTF(gltf);
      scene.add(gltf.scene);
    });
    /**
     * 加加载模型解码器
     */
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath("/draco/");
    glbLoader.setDRACOLoader(dracoLoader);
  };
  /**
   * 改变模型属性
   */
  const change = () => {
    GLTF!.scene.rotateY(Math.PI / 2);
    /**
     * 遍历所有子节点模型
     */
    GLTF!.scene.traverse((child) => {
      if (child instanceof THREE.Mesh) {
        console.log(child);
        child.castShadow = true;
        child.material.envMap = evMap;
        child.material.envMapIntensity = 1;
        /**
         * 透光率
         */
        // child.material.ior = 2;
        /**
         * 金属度  0 - 1
         */
        child.material.metalness = 1;
        child.material.roughness = 0.2;
        // gui.add(child.material, "metalness").min(0).max(1).step(0.01).name("金属度");
        child.material.needsUpdate = true;
      }
    });
  };

  /**
   * 地毯位置调整  为平面添加动画
   */
  const registerAnimate = () => {
    gsap.to(planeMesh.current!.position, {
      duration: 2,
      x: -5,
      y: 0,
      z: 0,
      yoyo: true,
      repeat: -1,
      ease: "none",
    });
  };
  useEffect(() => {
    changePlaneGeometry();
    addModel();
    registerAnimate();
  }, []);
  /**
   * 模型变化添加环境贴图
   */
  useEffect(() => {
    if (GLTF && evMap) {
      change();
    }
  }, [GLTF, evMap]);

  return (
    <>
      {/* 整个地毯 */}
      <group>
        <mesh ref={planeMesh}  receiveShadow={true}>
          <planeGeometry ref={planeGeometry} args={[20, 10]} />
          <meshStandardMaterial color={new THREE.Color('white')} side={THREE.DoubleSide}  />
        </mesh>
      </group>
      <AnimateModel gui={gui} GLTF={GLTF}></AnimateModel>
    </>
  );
}
